/*
 * Copyright 2012 Niklas Rehfeld
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.madpie.ui;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.ProgressMonitor;
import javax.swing.Timer;
import org.madpie.schemas.DiskType;
import org.madpie.schemas.Disks;
import org.madpie.transport.SshTermWrapper;
import org.madpie.transport.SshTransfer;
import org.madpie.util.SchemaUtils;

/**
 *
 * @author sand
 */
public class MainUI extends javax.swing.JFrame
{

    /**
     * The preferences key that holds the last used host
     */
    protected static final String LAST_HOST = "lastHost";
    /**
     * The preferences key that holds the last used user name
     */
    protected static final String LAST_USER = "lastUser";
    /**
     * The preferences key that holds the last used save location
     */
    protected static final String LAST_LOCATION = "lastLocation";
    /*
     * TODO These are defined twice, here and in SshTransfer. That is bad.
     */
    public static final String RAW_HW_FILE = "hw.info";
    public static final String RAW_CPU_FILE = "cpu.info";
    public static final String RAW_DISK_FILE = "disks.info";
    private String userName, targetHost, saveLocation;
    private static Preferences prefs;
    private HardwareMappingPanel hwPanel;

    /**
     * Creates new form MainUI
     */
    public MainUI()
    {
        prefs = Preferences.userNodeForPackage(this.getClass());
        initComponents();

        //should be in the init thing but netbeans doesn't like me...
        commandPanel = new CommandsPanel();
        mainPane.add("Commands", commandPanel);

        targetHost = prefs.get(LAST_HOST, "");
        userName = prefs.get(LAST_USER, "");
        hostField.setText(targetHost);
        userNameField.setText(userName);
        saveLocation = prefs.get(LAST_LOCATION, "");
        saveLocationField.setText(saveLocation);
        diskList.setCellRenderer(new DiskListRenderer());
        diskList.setEnabled(false);
        transferDiskButton.setEnabled(false);
        hwPanel = new HardwareMappingPanel(new File(saveLocation, "mapping.xml"));
        mainPane.add("Hardware Mapping", hwPanel);
        
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents()
    {

        mainPane = new javax.swing.JTabbedPane();
        transferPanel = new javax.swing.JPanel();
        hostLabel = new javax.swing.JLabel();
        hostField = new javax.swing.JTextField();
        saveLocationLabel = new javax.swing.JLabel();
        saveLocationField = new javax.swing.JTextField();
        saveLocationBrowseButton = new javax.swing.JButton();
        userNameLabel = new javax.swing.JLabel();
        userNameField = new javax.swing.JTextField();
        connectButton = new javax.swing.JButton();
        metadataPanel = new javax.swing.JPanel();
        hwFileNameLabel = new javax.swing.JLabel();
        hwFileNameInput = new javax.swing.JTextField();
        hwGetButton = new javax.swing.JButton();
        diskFileNameLabel = new javax.swing.JLabel();
        diskFileNameInput = new javax.swing.JTextField();
        diskGetButton = new javax.swing.JButton();
        diskListPane = new javax.swing.JScrollPane();
        diskList = new javax.swing.JList();
        diskLabel = new javax.swing.JLabel();
        transferDiskButton = new javax.swing.JButton();
        getChecksumButton = new javax.swing.JButton();
        emulatorPanel = new javax.swing.JPanel();
        progressBar = new javax.swing.JProgressBar();
        statusBar = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        exitMenuItem = new javax.swing.JMenuItem();
        editMenu = new javax.swing.JMenu();
        cutMenuItem = new javax.swing.JMenuItem();
        copyMenuItem = new javax.swing.JMenuItem();
        pasteMenuItem = new javax.swing.JMenuItem();
        deleteMenuItem = new javax.swing.JMenuItem();
        helpMenu = new javax.swing.JMenu();
        contentsMenuItem = new javax.swing.JMenuItem();
        aboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Madpie Imaging & Emulation");
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        setFocusable(false);
        setForeground(java.awt.Color.white);

        mainPane.setToolTipText("");

        hostLabel.setText("Host:");

        saveLocationLabel.setText("Save Location: ");

        saveLocationBrowseButton.setText("Browse");
        saveLocationBrowseButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                saveLocationBrowseButtonActionPerformed(evt);
            }
        });

        userNameLabel.setText("User Name: ");

        connectButton.setText("Test Connection");
        connectButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                connectButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout transferPanelLayout = new javax.swing.GroupLayout(transferPanel);
        transferPanel.setLayout(transferPanelLayout);
        transferPanelLayout.setHorizontalGroup(
            transferPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, transferPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(transferPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(userNameLabel)
                    .addGroup(transferPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(saveLocationLabel)
                        .addComponent(hostLabel, javax.swing.GroupLayout.Alignment.TRAILING)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(transferPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(saveLocationField)
                    .addComponent(hostField, javax.swing.GroupLayout.DEFAULT_SIZE, 227, Short.MAX_VALUE)
                    .addComponent(userNameField))
                .addGap(18, 18, 18)
                .addGroup(transferPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(saveLocationBrowseButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(connectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(24, 24, 24))
        );
        transferPanelLayout.setVerticalGroup(
            transferPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(transferPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(transferPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(saveLocationField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(saveLocationBrowseButton)
                    .addComponent(saveLocationLabel))
                .addGap(18, 18, 18)
                .addGroup(transferPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(hostLabel)
                    .addComponent(hostField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(transferPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(userNameLabel)
                    .addComponent(userNameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(connectButton))
                .addContainerGap(328, Short.MAX_VALUE))
        );

        mainPane.addTab("Connection", null, transferPanel, "Configure the network connection to the preservation target");

        hwFileNameLabel.setText("Hardware File Name: ");

        hwFileNameInput.setText("hw.xml");

        hwGetButton.setText("Get");
        hwGetButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                hwGetButtonActionPerformed(evt);
            }
        });

        diskFileNameLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        diskFileNameLabel.setText("Disk File Name: ");

        diskFileNameInput.setText("disks.xml");

        diskGetButton.setText("Get");
        diskGetButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                diskGetButtonActionPerformed(evt);
            }
        });

        diskList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        diskList.setToolTipText("Disks Found on remote server are displayed here.");
        diskListPane.setViewportView(diskList);

        diskLabel.setText("Disks Found: ");

        transferDiskButton.setText("Transfer Selected Disk Image");
        transferDiskButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                transferDiskButtonActionPerformed(evt);
            }
        });

        getChecksumButton.setText("Get Disk Checksum");
        getChecksumButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                getChecksumButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout metadataPanelLayout = new javax.swing.GroupLayout(metadataPanel);
        metadataPanel.setLayout(metadataPanelLayout);
        metadataPanelLayout.setHorizontalGroup(
            metadataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(metadataPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(metadataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(diskListPane)
                    .addGroup(metadataPanelLayout.createSequentialGroup()
                        .addGroup(metadataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(hwFileNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(diskFileNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(metadataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(metadataPanelLayout.createSequentialGroup()
                                .addComponent(hwFileNameInput, javax.swing.GroupLayout.DEFAULT_SIZE, 253, Short.MAX_VALUE)
                                .addGap(18, 18, 18)
                                .addComponent(hwGetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 97, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(metadataPanelLayout.createSequentialGroup()
                                .addComponent(diskFileNameInput)
                                .addGap(18, 18, 18)
                                .addComponent(diskGetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 97, javax.swing.GroupLayout.PREFERRED_SIZE))))
                    .addGroup(metadataPanelLayout.createSequentialGroup()
                        .addGroup(metadataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(diskLabel)
                            .addGroup(metadataPanelLayout.createSequentialGroup()
                                .addComponent(transferDiskButton)
                                .addGap(18, 18, 18)
                                .addComponent(getChecksumButton)))
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        metadataPanelLayout.setVerticalGroup(
            metadataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(metadataPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(metadataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(hwFileNameLabel)
                    .addComponent(hwFileNameInput, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(hwGetButton))
                .addGap(18, 18, 18)
                .addGroup(metadataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(diskFileNameLabel)
                    .addComponent(diskFileNameInput, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(diskGetButton))
                .addGap(18, 18, 18)
                .addComponent(diskLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(diskListPane, javax.swing.GroupLayout.DEFAULT_SIZE, 271, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(metadataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(transferDiskButton)
                    .addComponent(getChecksumButton))
                .addContainerGap())
        );

        mainPane.addTab("Metadata", null, metadataPanel, "Get and display metadata about the target machine");

        javax.swing.GroupLayout emulatorPanelLayout = new javax.swing.GroupLayout(emulatorPanel);
        emulatorPanel.setLayout(emulatorPanelLayout);
        emulatorPanelLayout.setHorizontalGroup(
            emulatorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 556, Short.MAX_VALUE)
        );
        emulatorPanelLayout.setVerticalGroup(
            emulatorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 439, Short.MAX_VALUE)
        );

        mainPane.addTab("Emulator", null, emulatorPanel, "Configure and launch the emulator");

        fileMenu.setMnemonic('f');
        fileMenu.setText("File");

        exitMenuItem.setMnemonic('x');
        exitMenuItem.setText("Exit");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                exitMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        editMenu.setMnemonic('e');
        editMenu.setText("Edit");

        cutMenuItem.setMnemonic('t');
        cutMenuItem.setText("Cut");
        editMenu.add(cutMenuItem);

        copyMenuItem.setMnemonic('y');
        copyMenuItem.setText("Copy");
        editMenu.add(copyMenuItem);

        pasteMenuItem.setMnemonic('p');
        pasteMenuItem.setText("Paste");
        editMenu.add(pasteMenuItem);

        deleteMenuItem.setMnemonic('d');
        deleteMenuItem.setText("Delete");
        editMenu.add(deleteMenuItem);

        menuBar.add(editMenu);

        helpMenu.setMnemonic('h');
        helpMenu.setText("Help");

        contentsMenuItem.setMnemonic('c');
        contentsMenuItem.setText("Contents");
        helpMenu.add(contentsMenuItem);

        aboutMenuItem.setMnemonic('a');
        aboutMenuItem.setText("About");
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        setJMenuBar(menuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mainPane)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(statusBar, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(mainPane)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(progressBar, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(statusBar, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        System.exit(0);
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void saveLocationBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveLocationBrowseButtonActionPerformed
        // TODO add your handling code here:
        JFileChooser ch = new JFileChooser(System.getProperty("user.dir", "./"));
        ch.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int ret = ch.showOpenDialog(transferPanel);
        if (ret == JFileChooser.APPROVE_OPTION)
        {
            File saveDir = ch.getSelectedFile();
            if (!saveDir.isDirectory() || !saveDir.canWrite())
            {
                JOptionPane.showMessageDialog(this, "Can't open directory "
                        + saveDir.getAbsolutePath()
                        + " for writing.", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            if (saveDir.listFiles().length > 0)
            {
                int confirm = JOptionPane.showConfirmDialog(this,
                        "The chosen directory is not empty. \n"
                        + "Are you sure you want to use it as the save directory?",
                        "Directory not empty",
                        JOptionPane.YES_NO_OPTION,
                        JOptionPane.WARNING_MESSAGE);
                if (confirm != JOptionPane.YES_OPTION)
                {
                    return;
                }
            }
            saveLocation = ch.getSelectedFile().getAbsolutePath();
            saveLocationField.setText(saveLocation);
            prefs.put(LAST_LOCATION, saveLocation);
            hwPanel.setOutputFile(new File(saveLocation, "mapping.xml"));
        }
    }//GEN-LAST:event_saveLocationBrowseButtonActionPerformed

    private void connectButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_connectButtonActionPerformed
    {//GEN-HEADEREND:event_connectButtonActionPerformed
        userName = userNameField.getText();
        targetHost = hostField.getText();
        if (targetHost.isEmpty())
        {
            JOptionPane.showMessageDialog(this,
                    "Must enter a host name or IP address",
                    "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }
        if (userName.isEmpty())
        {
            JOptionPane.showMessageDialog(this,
                    "Must enter user a user name.",
                    "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }

        prefs.put(LAST_HOST, targetHost);
        prefs.put(LAST_USER, userName);
        progressBar.setValue(50);
        progressBar.setIndeterminate(true);
        //TODO make this stuff use an external network transfer command.
//        progressBar.invalidate();
//        SshTermWrapper ssh = new SshTermWrapper(userName, targetHost);
//        boolean testok = ssh.testSshConnection();
        int i = doNetCommand("test");
        progressBar.setIndeterminate(false);
        progressBar.setValue(progressBar.getMaximum());
        if (i == 0)
        {
            statusBar.setText("Connection OK");
        }
        else
        {
            statusBar.setText("Connection Failed");
            JOptionPane.showMessageDialog(this, "Connection Failed", "Error",
                    JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_connectButtonActionPerformed

    private void hwGetButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_hwGetButtonActionPerformed
    {//GEN-HEADEREND:event_hwGetButtonActionPerformed

        progressBar.setValue(0);
        progressBar.setIndeterminate(true);
        //TODO need to check for nulls.
        File outputfile = new File(saveLocation, hwFileNameInput.getText());

        /*
         * TODO Maybe all of this should not write out temporary files, 
         * but keep them in memory or actually pipe them around.
         */
        File inputfile = new File(saveLocation, RAW_HW_FILE);


        int result = doNetCommand("hw");
        if (result == 0)
        {

            String hwCmd = commandPanel.getHwToXmlCommand();
            try
            {
                Process p = new ProcessBuilder(hwCmd, inputfile.
                        getAbsolutePath(),
                        outputfile.getAbsolutePath()).start();
                result = p.waitFor();
            } catch (IOException ex)
            {
                Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null,
                        ex);
                result = -1;
            } catch (InterruptedException e)
            {
                Logger.getLogger(MainUI.class.getName()).log(Level.WARNING,
                        "", e);
                result = -1;
            }
        }
        if (result == 0)
        {
            result = doNetCommand("cpu");
        }
        if (result == 0)
        {
            inputfile = new File(saveLocation, RAW_CPU_FILE);
            String cpuCmd = commandPanel.getCpuToXmlCommand();
            try
            {
                Process p = new ProcessBuilder(cpuCmd, inputfile.
                        getAbsolutePath(),
                        outputfile.getAbsolutePath()).start();
                result = p.waitFor();
            } catch (IOException ex)
            {
                Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null,
                        ex);
                result = -1;
            } catch (InterruptedException e)
            {
                Logger.getLogger(MainUI.class.getName()).log(Level.WARNING,
                        "", e);
                result = -1;
            }
        }
        statusBar.setText("Get HW " + (result == 0 ? "Successful" : "Failed"));
        if (result == 0)
        {
            hwPanel.getDiscoveredHwFromFile(outputfile);
        }
        progressBar.setIndeterminate(false);
        progressBar.setValue(progressBar.getMaximum());
    }//GEN-LAST:event_hwGetButtonActionPerformed

    private void diskGetButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_diskGetButtonActionPerformed
    {//GEN-HEADEREND:event_diskGetButtonActionPerformed
        int res = doNetCommand("disk");
//        statusBar.setText("Get Disks " + (res == 0 ? "Successful" : "Failed"));
        File f = new File(saveLocation, RAW_DISK_FILE);
        if (!f.exists() || !f.canRead())
        {
            statusBar.setForeground(Color.red);
            statusBar.setText("Get Disks Failed.");
            diskList.setEnabled(false);
            transferDiskButton.setEnabled(false);
            return;
        }
        String diskCmd = commandPanel.getDiskListToXmlCommand();
        ProcessBuilder diskPb = new ProcessBuilder(diskCmd, f.getAbsolutePath(),
                saveLocation + File.separator + diskFileNameInput.getText());
        try
        {
            Process p = diskPb.start();
            p.waitFor();

            File diskXmlFile = new File(saveLocation, diskFileNameInput.
                    getText());
            Disks d = SchemaUtils.readDiskFile(diskXmlFile);
            List<DiskType> disks = d.getDisk();
            diskList.setListData(disks.toArray());
        } catch (Exception ex)
        {
            Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE,
                    "Couldn't get disk list.", ex);
            statusBar.setForeground(Color.red);
            statusBar.setText("Couldn't parse disks.");
            diskList.setEnabled(false);
            transferDiskButton.setEnabled(false);
            return;
        }
        diskList.setEnabled(true);
        transferDiskButton.setEnabled(true);
        statusBar.setForeground(Color.black);
        statusBar.setText("Disk info collected.");

    }//GEN-LAST:event_diskGetButtonActionPerformed

    private void transferDiskButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_transferDiskButtonActionPerformed
    {//GEN-HEADEREND:event_transferDiskButtonActionPerformed
        DiskType selectedDisk = (DiskType) diskList.getSelectedValue();
        String disk = selectedDisk.getPath();
        doNetCommand("image", disk);//return value is alway 0.

        //TODO replace this, it is defined here and in SShTransfer.getDiskImage()
        File image = new File(saveLocation, disk.replaceAll("/", "_") + ".img");
        while (!image.exists())
        {
            try
            {
                image.wait(100);
            } catch (InterruptedException ex)
            {
                Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null,
                        ex);
            }
        }

        //wait and monitor progress.
        ProgressMonitor mon = new ProgressMonitor(this,
                "Transferring Disk " + disk, "Completed: ", 0,
                (int) (selectedDisk.getSize() / 1024L / 1024L));

        ActionListener transferProgressUpdater = new ActionListenerImpl(mon,
                image);


        Timer t = new Timer(1000, transferProgressUpdater);
        t.setInitialDelay(10000);
        t.start();

    }//GEN-LAST:event_transferDiskButtonActionPerformed

    private void getChecksumButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_getChecksumButtonActionPerformed
    {//GEN-HEADEREND:event_getChecksumButtonActionPerformed
        DiskType selectedDisk = (DiskType) diskList.getSelectedValue();
        String disk = selectedDisk.getPath();
        if (doNetCommand("checksum", disk) != 0)
        {
            JOptionPane.showMessageDialog(this,"Failed to create checksum.","Error.", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_getChecksumButtonActionPerformed

    /**
     * Note, this is a blocking method, as it waits for the command to return.
     *
     * @param command The type of metadata to collect. can be 'hw', 'disk' or
     * 'cpu'
     * @see SshTransfer#main(java.lang.String[])
     *
     * @return The return value of the command.
     */
    private int doNetCommand(String command, String... commandOpts)
    {
        String networkCmd = commandPanel.getNetworkTransferCommand();

        ProcessBuilder net;
        if (commandOpts == null || commandOpts.length == 0)
        {
            net = new ProcessBuilder(networkCmd, userName,
                    targetHost,
                    saveLocation, command);
        }
        else
        {
            net = new ProcessBuilder(networkCmd, userName,
                    targetHost,
                    saveLocation, command, commandOpts[0]);
        }

        int result = -1;
        try
        {
            Process p = net.start();
            result = p.waitFor();
        } catch (InterruptedException e)
        {
            Logger.getLogger(MainUI.class.getName()).log(Level.WARNING,
                    "", e);
        } catch (IOException e)
        {
            Logger.getLogger(MainUI.class.getName()).log(Level.WARNING, "", e);
        }
        return result;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[])
    {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try
        {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.
                    getInstalledLookAndFeels())
            {
                if ("Nimbus".equals(info.getName()))
                {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex)
        {
            java.util.logging.Logger.getLogger(MainUI.class.getName()).log(
                    java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex)
        {
            java.util.logging.Logger.getLogger(MainUI.class.getName()).log(
                    java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex)
        {
            java.util.logging.Logger.getLogger(MainUI.class.getName()).log(
                    java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex)
        {
            java.util.logging.Logger.getLogger(MainUI.class.getName()).log(
                    java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new MainUI().setVisible(true);
            }
        });
    }
    private CommandsPanel commandPanel;
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem aboutMenuItem;
    private javax.swing.JButton connectButton;
    private javax.swing.JMenuItem contentsMenuItem;
    private javax.swing.JMenuItem copyMenuItem;
    private javax.swing.JMenuItem cutMenuItem;
    private javax.swing.JMenuItem deleteMenuItem;
    private javax.swing.JTextField diskFileNameInput;
    private javax.swing.JLabel diskFileNameLabel;
    private javax.swing.JButton diskGetButton;
    private javax.swing.JLabel diskLabel;
    private javax.swing.JList diskList;
    private javax.swing.JScrollPane diskListPane;
    private javax.swing.JMenu editMenu;
    private javax.swing.JPanel emulatorPanel;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JButton getChecksumButton;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JTextField hostField;
    private javax.swing.JLabel hostLabel;
    private javax.swing.JTextField hwFileNameInput;
    private javax.swing.JLabel hwFileNameLabel;
    private javax.swing.JButton hwGetButton;
    private javax.swing.JTabbedPane mainPane;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JPanel metadataPanel;
    private javax.swing.JMenuItem pasteMenuItem;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JButton saveLocationBrowseButton;
    private javax.swing.JTextField saveLocationField;
    private javax.swing.JLabel saveLocationLabel;
    private javax.swing.JLabel statusBar;
    private javax.swing.JButton transferDiskButton;
    private javax.swing.JPanel transferPanel;
    private javax.swing.JTextField userNameField;
    private javax.swing.JLabel userNameLabel;
    // End of variables declaration//GEN-END:variables

    private class ActionListenerImpl implements ActionListener
    {

        private ProgressMonitor mon;
        private File image;

        public ActionListenerImpl(ProgressMonitor mon, File image)
        {
            this.mon = mon;
            this.image = image;
        }

        @Override
        public void actionPerformed(ActionEvent e)
        {
            if (mon.isCanceled())
            {
                JOptionPane.showMessageDialog(rootPane,
                        "Must cancel transfer manually: press ctrl+c in the terminal window.",
                        "Cancel transfer", JOptionPane.ERROR_MESSAGE);
                Timer t = (Timer) e.getSource();
                t.stop();
                return;
            }
            int size = (int) (image.length() / 1024L / 1024L);
            mon.setNote("Completed " + size + "MB");
            mon.setProgress(size);
            
        }
    }
}
